package com.bcbim.api_model.sys.interceptor;

import com.bcbim.common.response.annotation.Translate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @Description: Controller 返回值统一处理（码值翻译）
 * @Author haoshuai
 * @Date 2020/8/27
 * @Version V1.0
 **/
@Slf4j
@ControllerAdvice
public class MyResponseBody implements ResponseBodyAdvice {

    //框架 Response 返回的分页对象类名
    private static final String RETURN_PAGE_CLASS = "ReturnPageMsg";

    //返回对象getData方法和setData方法名
    private static final String GET_DATA_METHOD = "getData";
    private static final String SET_DATA_METHOD = "setData";

    /*
    这里直接返回true,表示对任何handler的responsebody都调用beforeBodyWrite方法
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    /**
     * @Description: 返回值码值翻译
     * @Param: Object
     * @Param: MethodParameter
     * @Param: MediaType
     * @Param: Class
     * @Param: ServerHttpRequest
     * @Param: ServerHttpResponse
     * @Return: java.lang.Object
     * @Author: haoshuai
     * @Date: 2020/8/27
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        Method method = methodParameter.getMethod();
        if (!method.isAnnotationPresent(Translate.class)) return o;

        Class<?> clazz = o.getClass();
        try {

            //获取返回对象 data 值
            Method getMethod = clazz.getMethod(GET_DATA_METHOD);
            Object data = getMethod.invoke(o);

            if (data==null) return o;

            //写入返回对象 data 值
            Method setMethod = getSetMethod(clazz);
            setMethod.invoke(o, TranslateHandle.translationData(data));

        } catch (NoSuchMethodException e) {
            log.error("字典翻译失败, errMsg={}", e);
        } catch (IllegalAccessException e) {
            log.error("字典翻译失败, errMsg={}", e);
        } catch (InvocationTargetException e) {
            log.error("字典翻译失败, errMsg={}", e);
        }
        return o;

    }

    /**
     * @Description: 获取返回对象赋值data方法
     * @Param: clazz
     * @Return: Method
     * @Author: haoshuai
     * @Date: 2020/8/27
     */
    private Method getSetMethod(Class<?> clazz) throws NoSuchMethodException {
        return clazz.getMethod(SET_DATA_METHOD, isReturnPageClass(clazz) ? List.class : Object.class);
    }

    /**
     * @Description: 判断返回对象是否为分页对象(ReturnPageMsg)
     * @Param: Class<?> clazz
     * @Return: boolean
     * @Author: haoshuai
     * @Date: 2020/8/28
     */
    private boolean isReturnPageClass(Class<?> clazz) {
        return clazz.toString().endsWith(RETURN_PAGE_CLASS);
    }

}
